package cn.kicsy.www.anonymous_bbs.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * OpenAPI文档转换为Markdown格式的工具类
 */
@Component
public class OpenApiToMarkdownConverter {

    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 将OpenAPI JSON文件转换为Markdown文档
     * @param jsonFilePath OpenAPI JSON文件路径
     * @param markdownFilePath 输出的Markdown文件路径
     */
    public void convertJsonToMarkdown(String jsonFilePath, String markdownFilePath) {
        try {
            // 读取JSON文件
            Map<String, Object> openApiSpec = objectMapper.readValue(new File(jsonFilePath), Map.class);
            
            // 创建Markdown内容
            StringBuilder markdown = new StringBuilder();
            
            // 添加标题和基本信息
            addTitleAndInfo(openApiSpec, markdown);
            
            // 添加路径信息
            addPaths(openApiSpec, markdown);
            
            // 添加数据模型
            addSchemas(openApiSpec, markdown);
            
            // 写入Markdown文件
            try (FileWriter writer = new FileWriter(markdownFilePath)) {
                writer.write(markdown.toString());
            }
            
            System.out.println("Markdown文档已生成: " + markdownFilePath);
        } catch (IOException e) {
            System.err.println("转换OpenAPI文档为Markdown时出错: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 添加标题和基本信息
     */
    private void addTitleAndInfo(Map<String, Object> openApiSpec, StringBuilder markdown) {
        Map<String, Object> info = (Map<String, Object>) openApiSpec.get("info");
        String title = (String) info.get("title");
        String description = (String) info.get("description");
        String version = (String) info.get("version");
        
        markdown.append("# ").append(title).append("\n\n");
        markdown.append("**版本**: ").append(version).append("\n\n");
        markdown.append("**描述**: ").append(description).append("\n\n");
        
        // 添加联系人信息
        if (info.containsKey("contact")) {
            Map<String, Object> contact = (Map<String, Object>) info.get("contact");
            markdown.append("## 联系方式\n\n");
            if (contact.containsKey("name")) {
                markdown.append("**名称**: ").append(contact.get("name")).append("\n");
            }
            if (contact.containsKey("email")) {
                markdown.append("**邮箱**: ").append(contact.get("email")).append("\n");
            }
            if (contact.containsKey("url")) {
                markdown.append("**网址**: ").append(contact.get("url")).append("\n");
            }
            markdown.append("\n");
        }
        
        // 添加许可证信息
        if (info.containsKey("license")) {
            Map<String, Object> license = (Map<String, Object>) info.get("license");
            markdown.append("## 许可证\n\n");
            if (license.containsKey("name")) {
                markdown.append("**名称**: ").append(license.get("name")).append("\n");
            }
            if (license.containsKey("url")) {
                markdown.append("**网址**: ").append(license.get("url")).append("\n");
            }
            markdown.append("\n");
        }
        
        markdown.append("---\n\n");
    }

    /**
     * 添加API路径信息
     */
    private void addPaths(Map<String, Object> openApiSpec, StringBuilder markdown) {
        markdown.append("## API 接口\n\n");
        
        Map<String, Object> paths = (Map<String, Object>) openApiSpec.get("paths");
        
        for (Map.Entry<String, Object> pathEntry : paths.entrySet()) {
            String path = pathEntry.getKey();
            Map<String, Object> pathItem = (Map<String, Object>) pathEntry.getValue();
            
            for (Map.Entry<String, Object> methodEntry : pathItem.entrySet()) {
                String method = methodEntry.getKey().toUpperCase();
                Map<String, Object> operation = (Map<String, Object>) methodEntry.getValue();
                
                markdown.append("### ").append(method).append(" ").append(path).append("\n\n");
                
                // 添加操作描述
                if (operation.containsKey("summary")) {
                    markdown.append("**摘要**: ").append(operation.get("summary")).append("\n\n");
                }
                if (operation.containsKey("description")) {
                    markdown.append("**描述**: ").append(operation.get("description")).append("\n\n");
                }
                
                // 添加参数
                if (operation.containsKey("parameters")) {
                    markdown.append("#### 参数\n\n");
                    markdown.append("| 名称 | 位置 | 描述 | 必填 | 类型 |\n");
                    markdown.append("|------|------|------|------|------|\n");
                    
                    List<Map<String, Object>> parameters = (List<Map<String, Object>>) operation.get("parameters");
                    for (Map<String, Object> param : parameters) {
                        String name = (String) param.get("name");
                        String in = (String) param.get("in");
                        String description = param.containsKey("description") ? (String) param.get("description") : "";
                        Boolean required = param.containsKey("required") ? (Boolean) param.get("required") : false;
                        String type = param.containsKey("schema") ? 
                                ((Map<String, Object>) param.get("schema")).get("type").toString() : 
                                (param.containsKey("type") ? param.get("type").toString() : "");
                        
                        markdown.append("| ").append(name).append(" | ").append(in).append(" | ")
                                .append(description).append(" | ").append(required ? "是" : "否").append(" | ")
                                .append(type).append(" |\n");
                    }
                    markdown.append("\n");
                }
                
                // 添加请求体
                if (operation.containsKey("requestBody")) {
                    markdown.append("#### 请求体\n\n");
                    Map<String, Object> requestBody = (Map<String, Object>) operation.get("requestBody");
                    if (requestBody.containsKey("description")) {
                        markdown.append("**描述**: ").append(requestBody.get("description")).append("\n\n");
                    }
                    
                    Map<String, Object> content = (Map<String, Object>) requestBody.get("content");
                    for (Map.Entry<String, Object> contentEntry : content.entrySet()) {
                        String mediaType = contentEntry.getKey();
                        Map<String, Object> media = (Map<String, Object>) contentEntry.getValue();
                        Map<String, Object> schema = (Map<String, Object>) media.get("schema");
                        
                        markdown.append("**媒体类型**: ").append(mediaType).append("\n\n");
                        
                        if (schema.containsKey("$ref")) {
                            String ref = (String) schema.get("$ref");
                            String schemaName = ref.substring(ref.lastIndexOf("/") + 1);
                            markdown.append("**模型**: ").append(schemaName).append("\n\n");
                        }
                    }
                }
                
                // 添加响应
                if (operation.containsKey("responses")) {
                    markdown.append("#### 响应\n\n");
                    markdown.append("| 状态码 | 描述 |\n");
                    markdown.append("|--------|------|\n");
                    
                    Map<String, Object> responses = (Map<String, Object>) operation.get("responses");
                    for (Map.Entry<String, Object> responseEntry : responses.entrySet()) {
                        String statusCode = responseEntry.getKey();
                        Map<String, Object> response = (Map<String, Object>) responseEntry.getValue();
                        String description = (String) response.get("description");
                        
                        markdown.append("| ").append(statusCode).append(" | ").append(description).append(" |\n");
                    }
                    markdown.append("\n");
                }
                
                markdown.append("---\n\n");
            }
        }
    }

    /**
     * 添加数据模型
     */
    private void addSchemas(Map<String, Object> openApiSpec, StringBuilder markdown) {
        if (!openApiSpec.containsKey("components")) {
            return;
        }
        
        Map<String, Object> components = (Map<String, Object>) openApiSpec.get("components");
        if (!components.containsKey("schemas")) {
            return;
        }
        
        markdown.append("## 数据模型\n\n");
        
        Map<String, Object> schemas = (Map<String, Object>) components.get("schemas");
        
        for (Map.Entry<String, Object> schemaEntry : schemas.entrySet()) {
            String schemaName = schemaEntry.getKey();
            Map<String, Object> schema = (Map<String, Object>) schemaEntry.getValue();
            
            markdown.append("### ").append(schemaName).append("\n\n");
            
            if (schema.containsKey("description")) {
                markdown.append("**描述**: ").append(schema.get("description")).append("\n\n");
            }
            
            if (schema.containsKey("properties")) {
                markdown.append("#### 属性\n\n");
                markdown.append("| 名称 | 类型 | 描述 |\n");
                markdown.append("|------|------|------|\n");
                
                Map<String, Object> properties = (Map<String, Object>) schema.get("properties");
                for (Map.Entry<String, Object> propEntry : properties.entrySet()) {
                    String propName = propEntry.getKey();
                    Map<String, Object> prop = (Map<String, Object>) propEntry.getValue();
                    String type = (String) prop.get("type");
                    String description = prop.containsKey("description") ? (String) prop.get("description") : "";
                    
                    markdown.append("| ").append(propName).append(" | ").append(type).append(" | ")
                            .append(description).append(" |\n");
                }
                markdown.append("\n");
            }
            
            markdown.append("---\n\n");
        }
    }
}